package br.ufrn.dimap.ase.squid.metrics.actions;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowActionDelegate;

import br.ufrn.dimap.ase.squid.core.models.squidmodel.Asset;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.Mapping;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.impl.ClassImpl;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.impl.CodePieceImpl;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.impl.FieldImpl;
import br.ufrn.dimap.ase.squid.core.models.squidmodel.impl.MethodImpl;
import br.ufrn.dimap.ase.squid.metrics.AbstractMetrics;
import br.ufrn.dimap.ase.squid.metrics.visitors.VisitorGranularidade;


/**
 * Our sample action implements workbench action delegate.
 * The action proxy will be created by the workbench and
 * shown in the UI. When the user tries to use the action,
 * this delegate will be created and execution will be 
 * delegated to it.
 * @see IWorkbenchWindowActionDelegate
 */
public class GranularityMetricsAction extends AbstractMetrics implements IWorkbenchWindowActionDelegate, IRunableMetrics {
	private IWorkbenchWindow window;
	/**
	 * The constructor.
	 */
	public GranularityMetricsAction() {
	}

	/* (non-Javadoc)
	 * @see br.ufrn.dimap.ase.squid.metrics.AbstractMetrics#runMetrics()
	 * 
	 * Chamado quando o calculo das metricas eh chamado pelo menu
	 */
	@Override
	public void runMetrics() {
		Iterator<String> it = mapping.keySet().iterator();
		
		VisitorGranularidade visitorGranularidade = null;
		while (it.hasNext()) {
			visitorGranularidade = new VisitorGranularidade(mapping);
			
			String featureName = it.next();
			List<Mapping> mappingFromFeature = mapping.get(featureName);
			
			for(Mapping mapping2 : mappingFromFeature){
				this.visitar(visitorGranularidade, mapping2, featureName);
			}
			
			result += String.format(
					"Feature: %s\n%s\n\n", 
					featureName, 
					visitorGranularidade
				);
		}
	}

	/* (non-Javadoc)
	 * @see br.ufrn.dimap.ase.squid.metrics.AbstractMetrics#runMetrics(java.lang.String)
	 * 
	 * Metodo chamado quando os calculos das metricas eh chamado pela view
	 */
	@Override
	public void runMetrics(String feature) {
		VisitorGranularidade visitorGranularidade = null;
		visitorGranularidade = new VisitorGranularidade(mapping);
		
		List<Mapping> mappingFromFeature = mapping.get(feature);
		System.out.println("Feature: " + feature);
		for(Mapping mapping2 : mappingFromFeature){
			this.visitar(visitorGranularidade, mapping2, feature);
		}
		
		resultados = visitorGranularidade.getResultados();
	}

	/**
	 * The action has been activated. The argument of the
	 * method represents the 'real' action sitting
	 * in the workbench UI.
	 * @see IWorkbenchWindowActionDelegate#run
	 */
	public void run(IAction action) {
		super.run();
	}
	
	private void visitar(VisitorGranularidade visitorGranularidade, Mapping mapping, String feature){
		if(mapping.getAssets() instanceof ClassImpl){
			visitorGranularidade.visit((ClassImpl) mapping.getAssets(), mapping, feature);
		}
		if(mapping.getAssets() instanceof FieldImpl){
			visitorGranularidade.visit((FieldImpl) mapping.getAssets(), mapping, feature);
		}
		if(mapping.getAssets() instanceof CodePieceImpl){
			visitorGranularidade.visit((CodePieceImpl) mapping.getAssets(), mapping, feature);
		}
		if(mapping.getAssets() instanceof MethodImpl){
			visitorGranularidade.visit((MethodImpl) mapping.getAssets(), mapping, feature);
		}
	}

	/**
	 * Selection in the workbench has been changed. We 
	 * can change the state of the 'real' action here
	 * if we want, but this can only happen after 
	 * the delegate has been created.
	 * @see IWorkbenchWindowActionDelegate#selectionChanged
	 */
	public void selectionChanged(IAction action, ISelection selection) {
	}

	/**
	 * We can use this method to dispose of any system
	 * resources we previously allocated.
	 * @see IWorkbenchWindowActionDelegate#dispose
	 */
	public void dispose() {
	}

	/**
	 * We will cache window object in order to
	 * be able to provide parent shell for the message dialog.
	 * @see IWorkbenchWindowActionDelegate#init
	 */
	public void init(IWorkbenchWindow window) {
		this.window = window;
	}
	
	public Map<String, List<Mapping>> getMappings() {
		return this.mapping;
	}
	
}